using System;
using System.Collections.Generic;
using System.Collections;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;
using BriansClimb;
using BriansClimb.DrawableGameObjects;
using BriansClimb.DrawableGameObjects.GameScenes;
using BriansClimb.DrawableGameObjects.ClimbingHolds;
using BriansClimb.DrawableGameObjects.Buttons;
using BriansClimb.GameObjects;

namespace BriansClimb.DrawableGameObjects
{
    /// <summary>
    /// This is a game component that implements the Stamina Bar and its Functionality.
    /// </summary>
    public class StaminaBar : DrawableGameComponent 
    {
        protected SpriteBatch spriteBatch;
        protected WallManager wallManager;
        protected PlayerClimbScene playerClimbScene;
        protected List<ClimbingHold> climbingHoldList;        
        protected Texture2D staminaBar;
        protected Texture2D staminaMeter;
        protected Vector2 meterPosition;
        protected Vector2 barPosition;        
        protected Vector2 meterSize;
        protected Vector2 barSize;

        protected int stamAllowance = 0;        
        protected bool noStamina = false;
        protected int strengthDrop;        

        //! Holds the number that determines the rate of the stamina bar
        protected float constantDrop;
        
        /// <summary>
        /// Creates an instance of StaminaBar which acts as a timer for the climber which can be recharged by rest holds.
        /// It is comprised of two components, the bar, which doesn't change, and the meter, which does change. The constructor
        /// creates both of these components and sizes them to fit together.
        /// </summary>
        /// <param name="game"></param>
        /// <param name="strengthDrop"></param>
        /// <param name="barPosition"></param>
        /// <param name="playerClimbScene"></param>
        public StaminaBar(Game game, int strengthDrop, Vector2 barPosition, PlayerClimbScene playerClimbScene)
            : base(game)
        {
            spriteBatch = (SpriteBatch)Game.Services.GetService(typeof(SpriteBatch));
            staminaMeter = game.Content.Load<Texture2D>(".\\Textures\\StaminaMeter");
            staminaBar = game.Content.Load<Texture2D>(".\\Textures\\StaminaBar");

            this.strengthDrop = strengthDrop;
            this.barPosition = barPosition;
            this.playerClimbScene = playerClimbScene;

            // Controls the size of the bar
            barSize.X = 420; barSize.Y = 48;

            //size and position of the meter inside the bar
            meterSize.X = (int)barSize.X - 20; 
            meterSize.Y = (int)barSize.Y / 2;
            meterPosition.X = (int)barPosition.X + 10; 
            meterPosition.Y = (int)barPosition.Y + (meterSize.Y / 2) - 1;

            // Initializing, this will be dynamically set
            constantDrop = 0.027f;

        }

        /// <summary>
        /// Checks whether a rest hold is being held and if so, whether to increase the stamina bar meter
        /// </summary>
        public void StaminaRest()
        {
            foreach (ClimbingHold holdObject in climbingHoldList)
            {
                //hold is being held, the meter is not full, the hold being held is a rest hold, the rest hold has not been already held.
                if (holdObject.IsBeingHeld == true && meterSize.X < 400 &&  holdObject.HoldFriction == 0 && !holdObject.HoldUsed)
                {
                    stamAllowance++;

                    meterSize.X = meterSize.X + 0.1f;

                    //rest hold only increases until the meter is full, or 600 game ticks go by
                    if (meterSize.X >= 400 || stamAllowance >= 600)
                        holdObject.HoldUsed = true;
                }                                            
            }
        }	                        
        
        /// <summary>
        /// Property which is set to true when the StaminaBar reaches zero.
        /// </summary>
        public bool NoStamina
        {
            get { return noStamina; }
        }

        /// <summary>
        /// Property which controls the rate the StaminaBar decreases.
        /// </summary>
        public float ConstantDrop
        {
            get { return constantDrop; }
            set { constantDrop = value; }
        }

        /// <summary>
        /// Allows the game component to update itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        public override void Update(GameTime gameTime)
        {
            //makes sure the hold list is always up-to-date
            climbingHoldList = playerClimbScene.ClimbingHoldList;

            StaminaRest();

            meterSize.X = meterSize.X - (float)constantDrop;

            //when meter is empty
            if (meterSize.X <= 0)            
                noStamina = true;                            

            base.Update(gameTime);
        }

        /// <summary>
        /// Draws two new rectangles, one which is the StaminaBar border and the other
        /// is the actual bar that changes with the climbers movements.
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Draw(GameTime gameTime)
        {
            spriteBatch.Draw(staminaBar, new Rectangle((int)barPosition.X, (int)barPosition.Y,
                                         (int)barSize.X, (int)barSize.Y), Color.White);

            spriteBatch.Draw(staminaMeter, new Rectangle((int)meterPosition.X, (int)meterPosition.Y,
                                         (int)meterSize.X, (int)meterSize.Y), Color.White);            
            base.Draw(gameTime);
        }
    }
}
